package cn.hexcloud.dga.governance.service.impl;

import cn.hexcloud.dga.common.util.SpringBeanProvider;
import cn.hexcloud.dga.ds.bean.TDsTaskDefinition;
import cn.hexcloud.dga.ds.service.TDsTaskDefinitionService;
import cn.hexcloud.dga.governance.assessor.Assessor;
import cn.hexcloud.dga.governance.bean.AssessParam;
import cn.hexcloud.dga.governance.bean.GovernanceAssessDetail;
import cn.hexcloud.dga.governance.bean.GovernanceMetric;
import cn.hexcloud.dga.governance.mapper.GovernanceAssessDetailMapper;
import cn.hexcloud.dga.governance.service.GovernanceAssessDetailService;
import cn.hexcloud.dga.governance.service.GovernanceMetricService;
import cn.hexcloud.dga.meta.bean.TableMetaInfo;
import cn.hexcloud.dga.meta.service.TableMetaInfoService;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 治理考评结果明细 服务实现类
 * </p>
 *
 * @author jiangdan7
 * @since 2023-08-28
 */
@Service
@DS("dga")
public class GovernanceAssessDetailServiceImpl extends ServiceImpl<GovernanceAssessDetailMapper, GovernanceAssessDetail> implements GovernanceAssessDetailService {
    @Autowired
    TableMetaInfoService tableMetaInfoService;

    @Autowired
    GovernanceMetricService governanceMetricService;

    @Autowired
    TDsTaskDefinitionService tDsTaskDefinitionService;

    /**
     * 声明连接池
     */
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(100, 100, 600, TimeUnit.SECONDS, new LinkedBlockingDeque<>());


    /**
     * 考评每张表 每个指标项 并把结果写入检查结果表
     */
    @Override
    public void assessAllTableMetrics(String assessDate) {
        /* 1 获得所有待考评表的列表 保存为list */
        List<TableMetaInfo> tableMetaInfoList = tableMetaInfoService.getTableMetaInfoList();

        /* 2 获得所有指标项的参数信息 保存为list */
        List<GovernanceMetric> governanceMetricList = governanceMetricService.list(new QueryWrapper<GovernanceMetric>().eq("is_disabled", 0));

        /* 3 获得所有待考评表的任务定义 */
        List<String> tableNameList = tableMetaInfoList.stream().map(a -> a.getSchemaName() + "." + a.getTableName()).collect(Collectors.toList());
        Map<String, TDsTaskDefinition> taskDefinitionMap = tDsTaskDefinitionService.getTableDefinitionMapByDt(assessDate, tableNameList);

        ArrayList<GovernanceAssessDetail> assessDetailList = new ArrayList<>(tableMetaInfoList.size() * governanceMetricList.size());
        // 5 准备一个异步结果的列表
        ArrayList<CompletableFuture<GovernanceAssessDetail>> completableFutureList = new ArrayList<>(tableMetaInfoList.size() * governanceMetricList.size());
        for (TableMetaInfo tableMetaInfo : tableMetaInfoList) {
            for (GovernanceMetric governanceMetric : governanceMetricList) {
                // 跳过白名单
                if (governanceMetric.getSkipAssessTables() != null) {
                    String[] skipTables = governanceMetric.getSkipAssessTables().split(",");
                    HashSet<String> skipTableSet = Sets.newHashSet(skipTables);
                    if (skipTableSet.contains(tableMetaInfo.getSchemaName() + "." + tableMetaInfo.getTableName())) {
                        continue;
                    }
                }
                Assessor assessor = SpringBeanProvider.getBean(governanceMetric.getMetricCode(), Assessor.class);
                AssessParam assessParam = new AssessParam();
                assessParam.setAssessDate(assessDate);
                assessParam.setTableMetaInfo(tableMetaInfo);
                assessParam.setGovernanceMetric(governanceMetric);
                assessParam.setTableMetaInfoList(tableMetaInfoList);
                assessParam.setTDsTaskDefinition(taskDefinitionMap.get(tableMetaInfo.getSchemaName() + "." + tableMetaInfo.getTableName()));
                // 异步方法
                CompletableFuture<GovernanceAssessDetail> completableFuture = CompletableFuture.supplyAsync(() -> {
                    // 业务逻辑
                    GovernanceAssessDetail governanceAssessDetail = assessor.metricAssess(assessParam);
                    return governanceAssessDetail;
                }, threadPoolExecutor);
                completableFutureList.add(completableFuture);
            }
        }
        // 异步集结
        List<GovernanceAssessDetail> governanceAccessDetailList = completableFutureList.stream().map(future -> future.join()).collect(Collectors.toList());
        saveBatch(governanceAccessDetailList, 500);
    }

    @Override
    public List<GovernanceAssessDetail> getLastProblemListByType(String governType, Integer pageNo, Integer pageSize) {

        //根据每页大小和页码计算显示行号
        int from = (pageNo - 1) * pageSize;

        QueryWrapper<GovernanceAssessDetail> queryWrapper = new QueryWrapper<GovernanceAssessDetail>()
                .eq("governance_type", governType)
                .lt("assess_score", 10)
                .inSql("assess_date", "select max(assess_date) from governance_assess_detail")
                .last("limit " + from + "," + pageSize);
        List<GovernanceAssessDetail> governanceAssessDetailList = list(queryWrapper);
        return governanceAssessDetailList;
    }

    @Override
    //根据治理类型进行分组聚合 所有问题求个数
    public List<Map<String, Object>> getLastProblemNum(){
        QueryWrapper<GovernanceAssessDetail> queryWrapper = new QueryWrapper<GovernanceAssessDetail>()
                .select("governance_type","count(*) ct")
                .lt("assess_score", 10)
                .inSql("assess_date","select max(assess_date) from governance_assess_detail")
                .groupBy("governance_type");

        List<Map<String, Object>> mapList = listMaps(queryWrapper);

        return mapList;
    }
}
